﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Text.RegularExpressions;

namespace SqlBlocks
{
    /// <summary>
    /// A migration container class, includes supporting data (Version number, etc) for the migration
    /// </summary>
    public class MigrationDescription : IComparable<MigrationDescription>
    {
        static string TypeNamePattern = @"(?<Name>\w+?)_(?<Order>\d+_?\d*)";
        /// <summary>
        /// The migration version number
        /// </summary>
        public double Version { get; private set; }

        /// <summary>
        /// The friendly name of the migration
        /// </summary>
        public string Name { get; private set; }

        /// <summary>
        /// The migration's group
        /// </summary>
        public string Group { get; private set; }

        public IMigration Migration { get; private set; }

        public MigrationDescription(double version, string group, string name, IMigration migration)
        {
            this.Group = group;
            this.Migration = migration;
            this.Version = version;
            this.Name = name;
        }

        
        /// <summary>
        /// Builds a migration definition from the specified type.
        /// </summary>
        /// <param name="t">A type that inherits from MigrationBase</param>
        /// <returns>The complete MigrationDescription.  Null if the type name isn't of the 
        /// form Name_VersionNumber</returns>
        public static MigrationDescription BuildFromType(Type t)
        {
            if (t == null)
            {
                throw new ArgumentNullException("t");
            }
            if (!typeof(IMigration).IsAssignableFrom(t))
            {
                throw new ArgumentException("The type must implement IMigration", "t");
            }
            Regex regex = new Regex(
                MigrationDescription.TypeNamePattern,
                RegexOptions.IgnoreCase
                | RegexOptions.CultureInvariant
                | RegexOptions.IgnorePatternWhitespace
                );

            Match match = regex.Match(t.Name);
            if (match.Success)
            {
                double order = -1;
                double.TryParse(match.Groups["Order"].Value.Replace('_', '.'), out order);
                MigrationDescription desc = new MigrationDescription(
                    order,
                    null,
                    match.Groups["Name"].Value,
                    (Migration)Activator.CreateInstance(t)
                    );
                return desc;
            }
            else
            {
                throw new ArgumentException("The type name must be in the form of Name_VersionNumber, ie: MigrationTest_001", "t");
            }
        }

        #region IComparable<MigrationDescription> Members

        public int CompareTo(MigrationDescription other)
        {
            if (string.IsNullOrEmpty(this.Group) && !string.IsNullOrEmpty(other.Group))
            {
                return -1;
            }
            else if (!string.IsNullOrEmpty(this.Group) && this.Group.CompareTo(other.Group) != 0)
            {
                return this.Group.CompareTo(other.Group);
            }
            return this.Version.CompareTo(other.Version);
        }

        #endregion
    }

    public class MigrationSet
    {
        public IList<MigrationDescription> Complete { get; private set; }
        public IList<MigrationDescription> Incomplete { get; private set; }

        public MigrationSet()
        {
            this.Complete = new List<MigrationDescription>();
            this.Incomplete = new List<MigrationDescription>();
        }
    }
}
